package principal;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.swing.JButton;
import javax.swing.JFrame;

import controlador.EtiquetaObservadorDePuntos;
import controlador.ObservadorDeBarcos;
import controlador.ObservadorDeMinas;
import controlador.ObservadorJuegoFinalizado;

import vista.VistaBarco;
import vista.VistaMina;

import modelo.Barco;
import modelo.Disparo;
import modelo.Juego;
import modelo.Mina;
import modelo.MinaSubmarinaDobleConRetardo;
import modelo.MinaSubmarinaPorContacto;
import modelo.MinaSubmarinaPuntualConRetardo;
import modelo.MinaSubmarinaTripleConRetardo;

import excepciones.LaPosicionYaTieneMinaExcepcion;

import fiuba.algo3.titiritero.dibujables.SuperficiePanel;
import fiuba.algo3.titiritero.modelo.GameLoop;
import java.awt.Font;

public class Principal {
	
	private final static int ANCHO_VENTANA = 800;
	private final static int ALTO_VENTANA = 600;
	
	public static void main(String[] args) {
		// Se crea el panel.
		SuperficiePanel panel = new SuperficiePanel();
        panel.setBackground(new Color(12, 183, 242));
        panel.setBounds(0,0, 500, 500);
        panel.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
        
		// Se crea la ventana.
		JFrame ventana = new JFrame("Batalla Navalgo");		
		ventana.getContentPane().setLayout(null);
		ventana.getContentPane().add(panel);  
		ventana.setBounds(0, 0, ANCHO_VENTANA, ALTO_VENTANA);
		ventana.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		ventana.setForeground(new Color(0, 0, 0));
		ventana.setResizable(false);
		ventana.setVisible(true);		
		panel.setImagen(panel.createImage(500, 500));

		// Se crea el game loop y se inicia el juego.
		final GameLoop gameLoop = new GameLoop(panel);		
		final Juego juego = new Juego();

		//gameLoop.agregar(new VistaTablero());
		
		// Se crean los botones para seleccionar las minas.
      	JButton botonDisparo = crearBotonParaMina("Disparo", Disparo.class, 0, juego);
      	JButton botonMSPCR = crearBotonParaMina("Mina Submarina Puntual Con Retardo", MinaSubmarinaPuntualConRetardo.class, 100, juego);
      	JButton botonMSDCR = crearBotonParaMina("Mina Submarina Doble Con Retardo", MinaSubmarinaDobleConRetardo.class, 200, juego);
      	JButton botonMSTCR = crearBotonParaMina("Mina Submarina Triple Con Retardo", MinaSubmarinaTripleConRetardo.class, 300, juego);
      	JButton botonMSPC = crearBotonParaMina("Mina Submarina Por Contacto", MinaSubmarinaPorContacto.class, 400, juego);

		// Se agregan los botones al panel.
      	ventana.getContentPane().add(botonDisparo);
      	ventana.getContentPane().add(botonMSPCR);
      	ventana.getContentPane().add(botonMSDCR);
      	ventana.getContentPane().add(botonMSTCR);
      	ventana.getContentPane().add(botonMSPC);
      	
      	// Se crea la etiqueta para mostrar los puntos.
      	EtiquetaObservadorDePuntos lblObservadorCantidadDePuntos = new EtiquetaObservadorDePuntos(juego);
      	lblObservadorCantidadDePuntos.setFont(new Font("Dialog", Font.BOLD, 20));
      	lblObservadorCantidadDePuntos.setBounds(75, 512, 258, 27);
      	
      	// Se agrega la etiqueta al panel.
      	ventana.getContentPane().add(lblObservadorCantidadDePuntos);
      	
      	// Se agrega la etiqueta como observador de GameLoop.
      	gameLoop.agregarObservador(lblObservadorCantidadDePuntos);
      	
		// Se agregan los barcos como objeto vivo, para que el movimiento sea fluido pixel a pixel.
		Collection<Barco> barcos = juego.getBarcos();
		Iterator<Barco> iteradorDeBarcos = barcos.iterator();
		// Tambien guarda las vistas de los barcos en un vector para poder sacarlas del gameloop
		// cuando el barco es destruido
		ArrayList<VistaBarco> vistasDeLosBarcos = new ArrayList<VistaBarco>();
      	while (iteradorDeBarcos.hasNext()) {
      		Barco barco = iteradorDeBarcos.next();
      		VistaBarco vistaBarco = new VistaBarco(barco);
    		gameLoop.agregar(vistaBarco);
    		gameLoop.agregar(vistaBarco.getPosicionable());
    		vistasDeLosBarcos.add(vistaBarco);
      	}

      	// Se crea un observador de minas que controla sus estados.
      	final ObservadorDeMinas observadorDeMinas = new ObservadorDeMinas(gameLoop);
      	gameLoop.agregarObservador(observadorDeMinas);
      	
      	// Se crea un observador para controlar la finalizacion del juego.
      	ObservadorJuegoFinalizado observadorDeJuegoFinalizado = new ObservadorJuegoFinalizado(juego,gameLoop);
      	gameLoop.agregarObservador(observadorDeJuegoFinalizado);
      	
		// Se crea un listener para los clics del mouse.
      	ventana.getContentPane().addMouseListener(new java.awt.event.MouseAdapter() {
			public void mousePressed(java.awt.event.MouseEvent e) {
				// para ver si anda es esto dsp lo borro
				System.out.println("mouseClicked(" + (e.getY())/50  + "," + (e.getX())/50+ ")");
				Mina minaPuesta;
				try {
					if((e.getY() < 500) && (e.getX() < 500)){
						minaPuesta = juego.ponerMina((e.getY())/50 ,(e.getX())/50);
						VistaMina vistaMina = new VistaMina(minaPuesta);
						gameLoop.agregar(vistaMina);
						observadorDeMinas.agregar(vistaMina);
					}
				} catch (LaPosicionYaTieneMinaExcepcion e1) {
					System.out.println(e1);
				}
			}
		});
		
      	// Se crea un observador de barcos que controla sus estados.
      	ObservadorDeBarcos observadorDeBarcos = new ObservadorDeBarcos(gameLoop, vistasDeLosBarcos);
      	gameLoop.agregarObservador(observadorDeBarcos);
		
		// Se setea la frecuencia e inicia la ejecucion.
		gameLoop.setFrecuencia(25);
		gameLoop.iniciarEjecucion();

		// Se agrega el juego como objeto vivo.
		gameLoop.agregar(juego);
	}

	private static JButton crearBotonParaMina(String tipoDeMina, final Class<? extends Mina> claseDeLaMina, int posicionY,final Juego juego) {      	
      	JButton boton = new JButton(tipoDeMina);
      	boton.addActionListener(new ActionListener() {
      		// el boton llama a seleccionar mina del juego.
			public void actionPerformed(ActionEvent e) {
				try {
					juego.seleccionarMina(claseDeLaMina.newInstance());
				} catch (InstantiationException | IllegalAccessException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
      	boton.setBounds(500, posicionY, 300, 100);
		return boton;
	}
}
